package io.mft.web.adapter.api;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import cn.hutool.core.util.ObjectUtil;
import io.mft.commons.config.ConfigProvider;
import io.mft.web.adapter.api.handler.ApiNotFundHandler;
import io.mft.web.adapter.api.handler.ApiProcessErrorHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * 自定义API请求处理映射器，目的是简化MVC原本复杂的接口查找逻辑，提高MVC请求处理效率
 * 
 * @说明：TODO
 * @类型名称：ApiRequestMappingHandlerMapping
 * @创建者: 胡常建
 * @创建时间: 2021年5月22日 上午10:37:46
 * @修改者: 胡常建
 * @修改时间: 2021年5月22日 上午10:37:46
 */
@Slf4j
public class ApiRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
	Map<String, RequestMappingInfo> mappingLookup = new ConcurrentHashMap<String, RequestMappingInfo>();

	@Override
	protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
		if (ObjectUtil.isNotEmpty(mapping.getName())) {
			mappingLookup.put(mapping.getName(), mapping);
		}
		super.registerHandlerMethod(handler, method, mapping);
	}

	@Override
	public void registerMapping(RequestMappingInfo mapping, Object handler, Method method) {
		mappingLookup.put(mapping.getName(), mapping);
		super.registerMapping(mapping, handler, method);
	}

	@Override
	protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		HandlerMethod handlerMethod = lookupHandlerMethodHere(lookupPath, request);
		if (ObjectUtil.isNull(handlerMethod)) {
			handlerMethod = super.lookupHandlerMethod(lookupPath, request);
		}
		return handlerMethod;
	}

	// 自己的查找逻辑，根据从请求头中获取服务名apiKey，进行匹配查找
	private HandlerMethod lookupHandlerMethodHere(String lookupPath, HttpServletRequest request) {
		int defaultLookupHandler=ConfigProvider.get("http.defaultLookupHandler", 1);
		String apiKey = request.getHeader("apiKey");
		if (ObjectUtil.isEmpty(apiKey)) {
			if (defaultLookupHandler==1) {
				return null;
			}
			apiKey = request.getParameter("apiKey");
		}
		if (!ObjectUtil.isEmpty(apiKey)) {
			try {
				List<HandlerMethod> methodList = this.getHandlerMethodsForMappingName(apiKey);
				if (methodList.size() > 0) {
					HandlerMethod handlerMethod = methodList.get(0);
					RequestMappingInfo requestMappingInfo = mappingLookup.get(apiKey);
					handleMatch(requestMappingInfo, lookupPath, request);
					return handlerMethod;
				}else {
					if (defaultLookupHandler==1) {
						return null;
					}
					List<HandlerMethod> methodList1 = this.getHandlerMethodsForMappingName(ApiNotFundHandler.class.getName());
					if (methodList1.size()>0) {
						HandlerMethod handlerMethod = methodList1.get(0);
						return handlerMethod;
					}else {
						return null;
					}
				}
			} catch (Exception e) {
				if (defaultLookupHandler==1) {
					return null;
				}
				List<HandlerMethod> methodList1 = this.getHandlerMethodsForMappingName(ApiProcessErrorHandler.class.getName());
				if (methodList1.size()>0) {
					HandlerMethod handlerMethod = methodList1.get(0);
					return handlerMethod;
				}else {
					return null;
				}
			}
		}else {
			if (defaultLookupHandler==1) {
				return null;
			}
			List<HandlerMethod> methodList1 = this.getHandlerMethodsForMappingName(ApiNotFundHandler.class.getName());
			if (methodList1.size()>0) {
				HandlerMethod handlerMethod = methodList1.get(0);
				return handlerMethod;
			}else {
				return null;
			}
		}
		
	}
}
